package cn.xn.hrms.domain.config;

import java.util.List;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import cn.xn.hrms.api.dto.res.UserDTO;
import cn.xn.hrms.domain.enums.ResultEnum;
import cn.xn.hrms.domain.utils.RedisUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.CollectionUtils;

import cn.xn.hrms.infrastructure.dao.UserRoleDao;
import cn.xn.hrms.api.dto.res.UserRoleDTO;
import cn.xn.hrms.domain.service.UserService;
import cn.xn.hrms.domain.utils.FunctionUtils;
import lombok.extern.slf4j.Slf4j;

/**
 * @author ysz
 */
@Slf4j
public class UserRealm extends AuthorizingRealm {

    @Resource
    private UserService userService;

    @Resource
    private UserRoleDao userRoleDao;

    @Resource
    private RedisUtils redisUtils;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JWTToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        UserDTO userDTO = (UserDTO) principalCollection.getPrimaryPrincipal();
        List<UserRoleDTO> userRoleList = userRoleDao.findAllByUserId(Long.valueOf(userDTO.getUserId()));
        // 用户和角色关系改为一对多
        FunctionUtils.isTrueOrFalse(!CollectionUtils.isEmpty(userRoleList)).trueOrFalseHandle(()->{
            List<String> roleNameList = userRoleList.stream().map(UserRoleDTO::getRoleName).distinct().collect(Collectors.toList());
            authorizationInfo.addRoles(roleNameList);

        },()->{});
        authorizationInfo.addStringPermission(null);
        return authorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken)
            throws AuthenticationException {
        String token = (String) authenticationToken.getCredentials();
        String username = JWTUtils.getUsername(token);

        if (username == null) {
            throw new AuthenticationException("token异常");
        }
        UserDTO userDTOBean = userService.findByUsername(username);

        if (!JWTUtils.verify(token, username, userDTOBean.getPassword())) {
            throw new AuthenticationException("密码错误");
        }
        // 判断用户多处登录
        String cacheToken = redisUtils.getString(username);
        if (StringUtils.isNotBlank(cacheToken) && !StringUtils.equals(cacheToken, token)) {
            throw new AuthenticationException(ResultEnum.LOG_IN_AGAIN.getMessage());
        }

        return new SimpleAuthenticationInfo(userDTOBean, token, getName());
    }
}
